summaryrefslogtreecommitdiff
path: root/app/[lng]/engineering/(engineering)
diff options
context:
space:
mode:
Diffstat (limited to 'app/[lng]/engineering/(engineering)')
-rw-r--r--app/[lng]/engineering/(engineering)/docu-list-rule/code-groups/page.tsx54
-rw-r--r--app/[lng]/engineering/(engineering)/docu-list-rule/combo-box-settings/page.tsx53
-rw-r--r--app/[lng]/engineering/(engineering)/docu-list-rule/document-class/page.tsx52
-rw-r--r--app/[lng]/engineering/(engineering)/docu-list-rule/layout.tsx69
-rw-r--r--app/[lng]/engineering/(engineering)/docu-list-rule/number-type-configs/page.tsx60
-rw-r--r--app/[lng]/engineering/(engineering)/docu-list-rule/number-types/page.tsx52
-rw-r--r--app/[lng]/engineering/(engineering)/docu-list-rule/page.tsx12
-rw-r--r--app/[lng]/engineering/(engineering)/document-list-only/layout.tsx17
-rw-r--r--app/[lng]/engineering/(engineering)/document-list-only/page.tsx98
-rw-r--r--app/[lng]/engineering/(engineering)/document-list-ship/page.tsx144
-rw-r--r--app/[lng]/engineering/(engineering)/faq/manage/actions.ts48
-rw-r--r--app/[lng]/engineering/(engineering)/faq/manage/page.tsx38
-rw-r--r--app/[lng]/engineering/(engineering)/faq/page.tsx62
-rw-r--r--app/[lng]/engineering/(engineering)/form-list/page.tsx75
-rw-r--r--app/[lng]/engineering/(engineering)/items/page.tsx68
-rw-r--r--app/[lng]/engineering/(engineering)/layout.tsx18
-rw-r--r--app/[lng]/engineering/(engineering)/projects/page.tsx75
-rw-r--r--app/[lng]/engineering/(engineering)/report/page.tsx105
-rw-r--r--app/[lng]/engineering/(engineering)/tag-numbering/page.tsx74
-rw-r--r--app/[lng]/engineering/(engineering)/tasks/page.tsx63
-rw-r--r--app/[lng]/engineering/(engineering)/tbe/page.tsx113
-rw-r--r--app/[lng]/engineering/(engineering)/vendor-check-list/page.tsx74
-rw-r--r--app/[lng]/engineering/(engineering)/vendor-data/form/[packageId]/[formId]/[projectId]/[contractId]/page.tsx79
-rw-r--r--app/[lng]/engineering/(engineering)/vendor-data/layout.tsx67
-rw-r--r--app/[lng]/engineering/(engineering)/vendor-data/page.tsx28
-rw-r--r--app/[lng]/engineering/(engineering)/vendor-data/tag/[id]/page.tsx43
-rw-r--r--app/[lng]/engineering/(engineering)/vendor-investigation/page.tsx65
27 files changed, 0 insertions, 1706 deletions
diff --git a/app/[lng]/engineering/(engineering)/docu-list-rule/code-groups/page.tsx b/app/[lng]/engineering/(engineering)/docu-list-rule/code-groups/page.tsx
deleted file mode 100644
index 5aebf15d..00000000
--- a/app/[lng]/engineering/(engineering)/docu-list-rule/code-groups/page.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import * as React from "react";
-import { type SearchParams } from "@/types/table";
-import { Shell } from "@/components/shell";
-import { Skeleton } from "@/components/ui/skeleton";
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
-import { getCodeGroups } from "@/lib/docu-list-rule/code-groups/service";
-import { CodeGroupsTable } from "@/lib/docu-list-rule/code-groups/table/code-groups-table";
-import { searchParamsCodeGroupsCache } from "@/lib/docu-list-rule/code-groups/validation";
-import { InformationButton } from "@/components/information/information-button";
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>;
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams;
- const search = searchParamsCodeGroupsCache.parse(searchParams);
-
- const promises = Promise.all([
- getCodeGroups({
- ...search,
- }),
- ]);
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">Code Group 정의</h2>
- <InformationButton pagePath="evcp/docu-list-rule/code-groups" />
- </div>
- {/* <p className="text-muted-foreground">
- 문서 번호에 사용될 수 있는 다양한 코드 그룹의 정의를 관리하는 페이지입니다.
- </p> */}
- </div>
- </div>
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}></React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={7}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["8rem", "12rem", "10rem", "10rem", "12rem", "8rem", "12rem"]}
- shrinkZero
- />
- }
- >
- <CodeGroupsTable promises={promises} />
- </React.Suspense>
- </Shell>
- );
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/docu-list-rule/combo-box-settings/page.tsx b/app/[lng]/engineering/(engineering)/docu-list-rule/combo-box-settings/page.tsx
deleted file mode 100644
index cf0bf02e..00000000
--- a/app/[lng]/engineering/(engineering)/docu-list-rule/combo-box-settings/page.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import * as React from "react";
-import { Shell } from "@/components/shell";
-import { Skeleton } from "@/components/ui/skeleton";
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
-import { getComboBoxCodeGroups } from "@/lib/docu-list-rule/combo-box-settings/service";
-import { ComboBoxSettingsTable } from "@/lib/docu-list-rule/combo-box-settings/table/combo-box-settings-table";
-import { InformationButton } from "@/components/information/information-button";
-import { searchParamsCodeGroupsCache } from "@/lib/docu-list-rule/code-groups/validation";
-
-interface IndexPageProps {
- searchParams: Promise<any>;
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams;
-
- const promises = Promise.all([
- getComboBoxCodeGroups(
- searchParamsCodeGroupsCache.parse(searchParams)
- ),
- ]);
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">Combo Box 설정</h2>
- <InformationButton pagePath="evcp/docu-list-rule/combo-box-settings" />
- </div>
- {/* <p className="text-muted-foreground">
- Combo Box 옵션을 관리하는 페이지입니다.
- 각 Code Group별로 Combo Box에 표시될 옵션들을 설정할 수 있습니다.
- </p> */}
- </div>
- </div>
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}></React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["8rem", "12rem", "10rem", "8rem", "12rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <ComboBoxSettingsTable promises={promises} />
- </React.Suspense>
- </Shell>
- );
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/docu-list-rule/document-class/page.tsx b/app/[lng]/engineering/(engineering)/docu-list-rule/document-class/page.tsx
deleted file mode 100644
index 5c2c600e..00000000
--- a/app/[lng]/engineering/(engineering)/docu-list-rule/document-class/page.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import * as React from "react";
-import { Shell } from "@/components/shell";
-import { Skeleton } from "@/components/ui/skeleton";
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
-import { getDocumentClassCodeGroups } from "@/lib/docu-list-rule/document-class/service";
-import { DocumentClassTable } from "@/lib/docu-list-rule/document-class/table/document-class-table";
-import { InformationButton } from "@/components/information/information-button";
-import { searchParamsDocumentClassCache } from "@/lib/docu-list-rule/document-class/validation";
-
-interface IndexPageProps {
- searchParams: Promise<any>;
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams;
-
- const promises = Promise.all([
- getDocumentClassCodeGroups(
- searchParamsDocumentClassCache.parse(searchParams)
- ),
- ]);
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">Document Class 관리</h2>
- <InformationButton pagePath="evcp/docu-list-rule/document-class" />
- </div>
- {/* <p className="text-muted-foreground">
- Document Class를 관리합니다.
- </p> */}
- </div>
- </div>
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}></React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={4}
- searchableColumnCount={1}
- filterableColumnCount={1}
- cellWidths={["10rem", "20rem", "10rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <DocumentClassTable promises={promises} />
- </React.Suspense>
- </Shell>
- );
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/docu-list-rule/layout.tsx b/app/[lng]/engineering/(engineering)/docu-list-rule/layout.tsx
deleted file mode 100644
index 25023e4b..00000000
--- a/app/[lng]/engineering/(engineering)/docu-list-rule/layout.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-import { Metadata } from "next"
-
-import { Separator } from "@/components/ui/separator"
-import { SidebarNav } from "@/components/layout/sidebar-nav"
-
-export const metadata: Metadata = {
- title: "Document Numbering Rule",
-}
-
-
-
-export default async function DocumentNumberingLayout({
- children,
- params,
-}: {
- children: React.ReactNode
- params: { lng: string }
-}) {
- const resolvedParams = await params
- const lng = resolvedParams.lng
-
- const sidebarNavItems = [
- {
- title: "Document Class 관리",
- href: `/${lng}/engineering/docu-list-rule/document-class`,
- },
- {
- title: "Code Group 정의",
- href: `/${lng}/engineering/docu-list-rule/code-groups`,
- },
- {
- title: "Combo Box 설정",
- href: `/${lng}/engineering/docu-list-rule/combo-box-settings`,
- },
- {
- title: "Number Type 관리",
- href: `/${lng}/engineering/docu-list-rule/number-types`,
- },
- {
- title: "Number Type별 설정",
- href: `/${lng}/engineering/docu-list-rule/number-type-configs`,
- },
- ]
-
- return (
- <>
- <div className="container py-6">
- <section className="overflow-hidden rounded-[0.5rem] border bg-background shadow">
- <div className="hidden space-y-6 p-10 pb-16 md:block">
- <div className="space-y-0.5">
- <h2 className="text-2xl font-bold tracking-tight">Document Numbering Rule (해양)</h2>
- <p className="text-muted-foreground">
- 벤더 제출 문서 리스트 작성 시에 사용되는 넘버링
- </p>
- </div>
-
- <Separator className="my-6" />
- <div className="flex flex-col space-y-8 lg:flex-row lg:space-x-12 lg:space-y-0">
- <aside className="-mx-4 lg:w-1/5">
- <SidebarNav items={sidebarNavItems} />
- </aside>
- <div className="flex-1 ">{children}</div>
- </div>
- </div>
- </section>
- </div>
- </>
- )
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/docu-list-rule/number-type-configs/page.tsx b/app/[lng]/engineering/(engineering)/docu-list-rule/number-type-configs/page.tsx
deleted file mode 100644
index 4195ba24..00000000
--- a/app/[lng]/engineering/(engineering)/docu-list-rule/number-type-configs/page.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import * as React from "react";
-import { Shell } from "@/components/shell";
-import { Skeleton } from "@/components/ui/skeleton";
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
-import { NumberTypeConfigsTable } from "@/lib/docu-list-rule/number-type-configs/table/number-type-configs-table";
-import { getNumberTypes } from "@/lib/docu-list-rule/number-types/service";
-import { InformationButton } from "@/components/information/information-button";
-
-interface IndexPageProps {
- searchParams: Promise<any>;
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams;
-
- const promises = Promise.all([
- getNumberTypes({
- page: 1,
- perPage: 1000, // 모든 Number Type을 가져오기 위해 큰 값 설정
- search: "",
- sort: [{ id: "id", desc: false }], // DB 등록 순서대로 정렬
- filters: [],
- joinOperator: "and",
- flags: ["advancedTable"],
- numberTypeId: "",
- description: "",
- isActive: ""
- }),
- ]);
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">Number Type별 설정</h2>
- <InformationButton pagePath="evcp/docu-list-rule/number-type-configs" />
- </div>
- {/* <p className="text-muted-foreground">
- 각 문서 번호 유형별로 어떤 코드 그룹들을 어떤 순서로 사용할지 설정하는 페이지입니다.
- </p> */}
- </div>
- </div>
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}></React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "12rem", "12rem", "12rem"]}
- shrinkZero
- />
- }
- >
- <NumberTypeConfigsTable promises={promises} />
- </React.Suspense>
- </Shell>
- );
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/docu-list-rule/number-types/page.tsx b/app/[lng]/engineering/(engineering)/docu-list-rule/number-types/page.tsx
deleted file mode 100644
index 6fa010c7..00000000
--- a/app/[lng]/engineering/(engineering)/docu-list-rule/number-types/page.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import * as React from "react";
-import { Shell } from "@/components/shell";
-import { Skeleton } from "@/components/ui/skeleton";
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton";
-import { NumberTypesTable } from "@/lib/docu-list-rule/number-types/table/number-types-table";
-import { getNumberTypes } from "@/lib/docu-list-rule/number-types/service";
-import { InformationButton } from "@/components/information/information-button";
-import { searchParamsNumberTypesCache } from "@/lib/docu-list-rule/number-types/validation";
-
-interface IndexPageProps {
- searchParams: Promise<any>;
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams;
-
- const promises = Promise.all([
- getNumberTypes(
- searchParamsNumberTypesCache.parse(searchParams)
- ),
- ]);
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">Number Type 관리</h2>
- <InformationButton pagePath="evcp/docu-list-rule/number-types" />
- </div>
- {/* <p className="text-muted-foreground">
- 문서 번호 유형을 추가, 수정, 삭제할 수 있는 페이지입니다.
- </p> */}
- </div>
- </div>
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}></React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={4}
- searchableColumnCount={1}
- filterableColumnCount={0}
- cellWidths={["10rem", "20rem", "10rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <NumberTypesTable promises={promises} />
- </React.Suspense>
- </Shell>
- );
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/docu-list-rule/page.tsx b/app/[lng]/engineering/(engineering)/docu-list-rule/page.tsx
deleted file mode 100644
index b8d3559f..00000000
--- a/app/[lng]/engineering/(engineering)/docu-list-rule/page.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { redirect } from "next/navigation"
-
-
-export default async function DocumentNumberingPage({
- params,
-}: {
- params: Promise<{ lng: string }>
-}) {
- const resolvedParams = await params;
- // Code Group 페이지로 리다이렉트
- redirect(`/${resolvedParams.lng}/engineering/docu-list-rule/document-class`)
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/document-list-only/layout.tsx b/app/[lng]/engineering/(engineering)/document-list-only/layout.tsx
deleted file mode 100644
index 17e78c0a..00000000
--- a/app/[lng]/engineering/(engineering)/document-list-only/layout.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import { Shell } from "@/components/shell"
-import VendorDocumentListClientEvcp from "@/components/document-lists/vendor-doc-list-client-evcp"
-
-// Layout 컴포넌트는 서버 컴포넌트입니다
-export default async function EvcpDocuments({
- children,
-}: {
- children: React.ReactNode
-}) {
- return (
- <Shell className="gap-2">
- <VendorDocumentListClientEvcp>
- {children}
- </VendorDocumentListClientEvcp>
- </Shell>
- )
-}
diff --git a/app/[lng]/engineering/(engineering)/document-list-only/page.tsx b/app/[lng]/engineering/(engineering)/document-list-only/page.tsx
deleted file mode 100644
index 5b49a6ef..00000000
--- a/app/[lng]/engineering/(engineering)/document-list-only/page.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-// evcp/document-list-only/page.tsx - 전체 계약 대상 문서 목록
-import * as React from "react"
-import { Suspense } from "react"
-import { Skeleton } from "@/components/ui/skeleton"
-import { type SearchParams } from "@/types/table"
-import { getValidFilters } from "@/lib/data-table"
-import { DocumentStagesTable } from "@/lib/vendor-document-list/plant/document-stages-table"
-import { documentStageSearchParamsCache } from "@/lib/vendor-document-list/plant/document-stage-validations"
-import { getDocumentStagesOnly } from "@/lib/vendor-document-list/plant/document-stages-service"
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-// 문서 테이블 래퍼 컴포넌트 (전체 계약용)
-async function DocumentTableWrapper({
- searchParams
-}: {
- searchParams: SearchParams
-}) {
- const search = documentStageSearchParamsCache.parse(searchParams)
- const validFilters = getValidFilters(search.filters)
-
- // 필터 타입 변환
- const convertedFilters = validFilters.map(filter => ({
- id: (filter.id || filter.rowId) as string,
- value: filter.value,
- operator: (filter.operator === 'iLike' ? 'ilike' :
- filter.operator === 'notILike' ? 'notin' :
- filter.operator === 'isEmpty' ? 'eq' :
- filter.operator === 'isNotEmpty' ? 'ne' :
- filter.operator === 'isBetween' ? 'eq' :
- filter.operator === 'isRelativeToToday' ? 'eq' :
- filter.operator || 'eq') as 'eq' | 'in' | 'ne' | 'lt' | 'lte' | 'gt' | 'gte' | 'like' | 'ilike' | 'notin'
- }))
-
- // evcp: 전체 계약 대상으로 문서 조회
- const documentsPromise = getDocumentStagesOnly({
- ...search,
- filters: convertedFilters,
- }, -1) // 세션에서 자동으로 도메인 감지
-
- return (
- <DocumentStagesTable
- promises={Promise.all([documentsPromise])}
- contractId={-1} // 전체 계약을 의미
- projectType="plant" // 기본값으로 plant 사용
- />
- )
-}
-
-function TableLoadingSkeleton() {
- return (
- <div className="space-y-4">
- <div className="flex items-center justify-between">
- <Skeleton className="h-6 w-32" />
- <div className="flex items-center gap-2">
- <Skeleton className="h-8 w-20" />
- <Skeleton className="h-8 w-24" />
- </div>
- </div>
- <div className="rounded-md border">
- <div className="p-4">
- <div className="space-y-3">
- {Array.from({ length: 5 }).map((_, i) => (
- <div key={i} className="flex items-center space-x-4">
- <Skeleton className="h-4 w-4" />
- <Skeleton className="h-4 w-24" />
- <Skeleton className="h-4 w-48" />
- <Skeleton className="h-4 w-20" />
- <Skeleton className="h-4 w-16" />
- <Skeleton className="h-4 w-12" />
- </div>
- ))}
- </div>
- </div>
- </div>
- </div>
- )
-}
-
-// 메인 페이지 컴포넌트
-export default async function DocumentStagesManagementPage({
- searchParams
-}: IndexPageProps) {
- const resolvedSearchParams = await searchParams
-
- return (
- <div className="mx-auto">
- {/* 문서 테이블 */}
- <Suspense fallback={<TableLoadingSkeleton />}>
- <DocumentTableWrapper
- searchParams={resolvedSearchParams}
- />
- </Suspense>
- </div>
- )
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/document-list-ship/page.tsx b/app/[lng]/engineering/(engineering)/document-list-ship/page.tsx
deleted file mode 100644
index e3915419..00000000
--- a/app/[lng]/engineering/(engineering)/document-list-ship/page.tsx
+++ /dev/null
@@ -1,144 +0,0 @@
-// page.tsx (간단한 Promise 생성과 로그인 처리)
-import * as React from "react"
-import { type SearchParams } from "@/types/table"
-import { getValidFilters } from "@/lib/data-table"
-import { Skeleton } from "@/components/ui/skeleton"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { Shell } from "@/components/shell"
-import { searchParamsShipDocuCache } from "@/lib/vendor-document-list/validations"
-import { getServerSession } from "next-auth"
-import { authOptions } from "@/app/api/auth/[...nextauth]/route"
-import Link from "next/link"
-import { Button } from "@/components/ui/button"
-import { LogIn } from "lucide-react"
-import { getUserVendorDocumentStats, getUserVendorDocumentStatsAll, getUserVendorDocuments, getUserVendorDocumentsAll } from "@/lib/vendor-document-list/enhanced-document-service"
-import { UserVendorDocumentDisplay } from "@/components/ship-vendor-document/user-vendor-document-table-container"
-import { InformationButton } from "@/components/information/information-button"
-import { UserVendorALLDocumentDisplay } from "@/components/ship-vendor-document-all/user-vendor-document-table-container"
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams
- const search = searchParamsShipDocuCache.parse(searchParams)
- const validFilters = getValidFilters(search.filters)
-
- // Get session
- const session = await getServerSession(authOptions)
-
- // Check if user is logged in
- if (!session || !session.user) {
- return (
- <Shell className="gap-6">
- <div className="flex items-center justify-between">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">
- 문서 관리
- </h2>
-
- </div>
- {/* <p className="text-muted-foreground">
- 소속 회사의 모든 도서/도면을 확인하고 관리합니다.
- </p> */}
- </div>
- </div>
-
- <div className="flex flex-col items-center justify-center py-12 text-center">
- <div className="rounded-lg border border-dashed p-10 shadow-sm">
- <h3 className="mb-2 text-xl font-semibold">로그인이 필요합니다</h3>
- <p className="mb-6 text-muted-foreground">
- 문서를 확인하려면 먼저 로그인하세요.
- </p>
- <Button size="lg" asChild>
- <Link href="/partners">
- <LogIn className="mr-2 h-4 w-4" />
- 로그인하기
- </Link>
- </Button>
- </div>
- </div>
- </Shell>
- )
- }
-
- // User is logged in, get user ID
- const requesterId = session.user.id ? Number(session.user.id) : null
-
- if (!requesterId) {
- return (
- <Shell className="gap-6">
- <div className="flex items-center justify-between">
- <div>
- <h2 className="text-2xl font-bold tracking-tight">
- Document Management
- </h2>
- </div>
- </div>
- <div className="flex flex-col items-center justify-center py-12 text-center">
- <div className="rounded-lg border border-dashed p-10 shadow-sm">
- <h3 className="mb-2 text-xl font-semibold">계정 오류</h3>
- <p className="mb-6 text-muted-foreground">
- 사용자 정보가 올바르게 설정되지 않았습니다. 관리자에게 문의하세요.
- </p>
- </div>
- </div>
- </Shell>
- )
- }
-
- // 검색 파라미터 정리
- const searchInput = {
- ...search,
- filters: validFilters,
- }
-
- // Promise 생성 (모든 데이터를 페이지에서 처리)
- const documentsPromise = getUserVendorDocumentsAll(requesterId, searchInput)
- const statsPromise = getUserVendorDocumentStatsAll(requesterId)
-
- // Promise.all로 감싸서 전달
- const allPromises = Promise.all([documentsPromise, statsPromise])
- const statsResult = await documentsPromise
-
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">
- 조선 Document Management
- </h2>
- <InformationButton pagePath="evcp/document-list-ship" />
- </div>
- <p className="text-muted-foreground">
-
- </p>
- </div>
- </div>
-
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- {/* DateRangePicker can go here */}
- </React.Suspense>
-
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={8}
- searchableColumnCount={1}
- filterableColumnCount={3}
- cellWidths={["10rem", "30rem", "15rem", "15rem", "15rem", "15rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <UserVendorALLDocumentDisplay
- allPromises={allPromises}
- />
- </React.Suspense>
- </Shell>
- )
-}
-
diff --git a/app/[lng]/engineering/(engineering)/faq/manage/actions.ts b/app/[lng]/engineering/(engineering)/faq/manage/actions.ts
deleted file mode 100644
index bc443a8a..00000000
--- a/app/[lng]/engineering/(engineering)/faq/manage/actions.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-'use server';
-
-import { promises as fs } from 'fs';
-import path from 'path';
-import { FaqCategory } from '@/components/faq/FaqCard';
-import { fallbackLng } from '@/i18n/settings';
-
-const FAQ_CONFIG_PATH = path.join(process.cwd(), 'config', 'faqDataConfig.ts');
-
-export async function updateFaqData(lng: string, newData: FaqCategory[]) {
- try {
- const fileContent = await fs.readFile(FAQ_CONFIG_PATH, 'utf-8');
- const dataMatch = fileContent.match(/export const faqCategories[^=]*=\s*(\{[\s\S]*\});/);
- if (!dataMatch) {
- throw new Error('FAQ 데이터 형식이 올바르지 않습니다.');
- }
-
- const allData = eval(`(${dataMatch[1]})`);
- const updatedData = {
- ...allData,
- [lng]: newData
- };
-
- const newFileContent = `import { FaqCategory } from "@/components/faq/FaqCard";\n\ninterface LocalizedFaqCategories {\n [lng: string]: FaqCategory[];\n}\n\nexport const faqCategories: LocalizedFaqCategories = ${JSON.stringify(updatedData, null, 4)};`;
- await fs.writeFile(FAQ_CONFIG_PATH, newFileContent, 'utf-8');
-
- return { success: true };
- } catch (error) {
- console.error('FAQ 데이터 업데이트 중 오류 발생:', error);
- return { success: false, error: '데이터 업데이트 중 오류가 발생했습니다.' };
- }
-}
-
-export async function getFaqData(lng: string): Promise<{ data: FaqCategory[] }> {
- try {
- const fileContent = await fs.readFile(FAQ_CONFIG_PATH, 'utf-8');
- const dataMatch = fileContent.match(/export const faqCategories[^=]*=\s*(\{[\s\S]*\});/);
- if (!dataMatch) {
- throw new Error('FAQ 데이터 형식이 올바르지 않습니다.');
- }
-
- const allData = eval(`(${dataMatch[1]})`);
- return { data: allData[lng] || allData[fallbackLng] || [] };
- } catch (error) {
- console.error('FAQ 데이터 읽기 중 오류 발생:', error);
- return { data: [] };
- }
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/faq/manage/page.tsx b/app/[lng]/engineering/(engineering)/faq/manage/page.tsx
deleted file mode 100644
index 011bbfa4..00000000
--- a/app/[lng]/engineering/(engineering)/faq/manage/page.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import { FaqManager } from '@/components/faq/FaqManager';
-import { getFaqData, updateFaqData } from './actions';
-import { revalidatePath } from 'next/cache';
-import { FaqCategory } from '@/components/faq/FaqCard';
-
-interface Props {
- params: {
- lng: string;
- }
-}
-
-export default async function FaqManagePage(props: Props) {
- const resolvedParams = await props.params
- const lng = resolvedParams.lng
- const { data } = await getFaqData(lng);
-
- async function handleSave(newData: FaqCategory[]) {
- 'use server';
- await updateFaqData(lng, newData);
- revalidatePath(`/${lng}/evcp/faq`);
- }
-
- return (
- <div className="container py-6">
- <section className="overflow-hidden rounded-[0.5rem] border bg-background shadow">
- <div className="space-y-6 p-10 pb-16">
- <div className="space-y-0.5">
- <h2 className="text-2xl font-bold tracking-tight">FAQ Management</h2>
- <p className="text-muted-foreground">
- Manage FAQ categories and items for {lng.toUpperCase()} language.
- </p>
- </div>
- <FaqManager initialData={data} onSave={handleSave} lng={lng} />
- </div>
- </section>
- </div>
- );
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/faq/page.tsx b/app/[lng]/engineering/(engineering)/faq/page.tsx
deleted file mode 100644
index 9b62b7e4..00000000
--- a/app/[lng]/engineering/(engineering)/faq/page.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import { Separator } from "@/components/ui/separator"
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
-import { faqCategories } from "@/config/faqDataConfig"
-import { FaqCard } from "@/components/faq/FaqCard"
-import { Button } from "@/components/ui/button"
-import { Settings } from "lucide-react"
-import Link from "next/link"
-import { fallbackLng } from "@/i18n/settings"
-
-interface Props {
- params: {
- lng: string;
- }
-}
-
-export default async function FaqPage(props: Props) {
- const resolvedParams = await props.params
- const lng = resolvedParams.lng
- const localizedFaqCategories = faqCategories[lng] || faqCategories[fallbackLng];
-
- return (
- <div className="container py-6">
- <section className="overflow-hidden rounded-[0.5rem] border bg-background shadow">
- <div className="space-y-6 p-10 pb-16">
- <div className="flex justify-between items-center">
- <div className="space-y-0.5">
- <h2 className="text-2xl font-bold tracking-tight">Frequently Asked Questions</h2>
- <p className="text-muted-foreground">
- Find answers to common questions about using the EVCP system.
- </p>
- </div>
- <Link href={`/${lng}/evcp/faq/manage`}>
- <Button variant="outline">
- <Settings className="w-4 h-4 mr-2" />
- Manage FAQ
- </Button>
- </Link>
- </div>
- <Separator className="my-6" />
-
- <Tabs defaultValue={localizedFaqCategories[0]?.label} className="space-y-4">
- <TabsList>
- {localizedFaqCategories.map((category) => (
- <TabsTrigger key={category.label} value={category.label}>
- {category.label}
- </TabsTrigger>
- ))}
- </TabsList>
-
- {localizedFaqCategories.map((category) => (
- <TabsContent key={category.label} value={category.label} className="space-y-4">
- {category.items.map((item, index) => (
- <FaqCard key={index} item={item} />
- ))}
- </TabsContent>
- ))}
- </Tabs>
- </div>
- </section>
- </div>
- )
-}
diff --git a/app/[lng]/engineering/(engineering)/form-list/page.tsx b/app/[lng]/engineering/(engineering)/form-list/page.tsx
deleted file mode 100644
index a2c6fbb9..00000000
--- a/app/[lng]/engineering/(engineering)/form-list/page.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-import * as React from "react"
-import { type SearchParams } from "@/types/table"
-
-import { getValidFilters } from "@/lib/data-table"
-import { Skeleton } from "@/components/ui/skeleton"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { Shell } from "@/components/shell"
-import { searchParamsCache } from "@/lib/form-list/validation"
-import { ItemsTable } from "@/lib/items/table/items-table"
-import { getFormLists } from "@/lib/form-list/service"
-import { FormListsTable } from "@/lib/form-list/table/formLists-table"
-
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams
- const search = searchParamsCache.parse(searchParams)
-
- const validFilters = getValidFilters(search.filters)
-
- const promises = Promise.all([
- getFormLists({
- ...search,
- filters: validFilters,
- }),
-
- ])
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <h2 className="text-2xl font-bold tracking-tight">
- 레지스터 목록 from S-EDP
- </h2>
- {/* <p className="text-muted-foreground">
- 협력업체 데이터 입력을 위한 레지스터 목록 리스트입니다.{" "}
- <span className="inline-flex items-center whitespace-nowrap">
- <Ellipsis className="size-3" />
- <span className="ml-1">버튼</span>
- </span>
- 을 통해 담당자 연락처, 입찰 이력, 계약 이력, 패키지 내용 등을 확인 할 수 있습니다.
- </p> */}
- </div>
- </div>
- </div>
-
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- {/* <DateRangePicker
- triggerSize="sm"
- triggerClassName="ml-auto w-56 sm:w-60"
- align="end"
- shallow={false}
- /> */}
- </React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <FormListsTable promises={promises} />
- </React.Suspense>
- </Shell>
- )
-}
diff --git a/app/[lng]/engineering/(engineering)/items/page.tsx b/app/[lng]/engineering/(engineering)/items/page.tsx
deleted file mode 100644
index f8d9a5b1..00000000
--- a/app/[lng]/engineering/(engineering)/items/page.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-// app/items/page.tsx (업데이트)
-import * as React from "react"
-import { type SearchParams } from "@/types/table"
-
-import { Skeleton } from "@/components/ui/skeleton"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { Shell } from "@/components/shell"
-import { searchParamsCache } from "@/lib/items/validations"
-import { getItems } from "@/lib/items/service"
-import { ItemsTable } from "@/lib/items/table/items-table"
-import { ViewModeToggle } from "@/components/data-table/view-mode-toggle"
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams
- const search = searchParamsCache.parse(searchParams)
-
- // pageSize 기반으로 모드 자동 결정
- const isInfiniteMode = search.perPage >= 1_000_000
-
- // 페이지네이션 모드일 때만 서버에서 데이터 가져오기
- // 무한 스크롤 모드에서는 클라이언트에서 SWR로 데이터 로드
- const promises = isInfiniteMode
- ? undefined
- : Promise.all([
- getItems(search), // searchParamsCache의 결과를 그대로 사용
- ])
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <h2 className="text-2xl font-bold tracking-tight">
- 패키지 넘버
- </h2>
- {/* <p className="text-muted-foreground">
- S-EDP로부터 수신된 패키지 정보이며 PR 전 입찰, 견적에 사용되며 벤더 데이터, 문서와 연결됩니다.
- </p> */}
- </div>
- </div>
-
- </div>
-
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- {/* DateRangePicker 등 추가 컴포넌트 */}
- </React.Suspense>
-
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- {/* 통합된 ItemsTable 컴포넌트 사용 */}
- <ItemsTable promises={promises} />
- </React.Suspense>
- </Shell>
- )
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/layout.tsx b/app/[lng]/engineering/(engineering)/layout.tsx
deleted file mode 100644
index 82b53307..00000000
--- a/app/[lng]/engineering/(engineering)/layout.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { ReactNode } from 'react';
-import { Header } from '@/components/layout/Header';
-import { SiteFooter } from '@/components/layout/Footer';
-
-export default function EvcpLayout({ children }: { children: ReactNode }) {
- return (
- <div className="relative flex min-h-svh flex-col bg-background">
- {/* <div className="relative flex min-h-svh flex-col bg-slate-100 "> */}
- <Header />
- <main className="flex flex-1 flex-col">
- <div className='container-wrapper'>
- {children}
- </div>
- </main>
- <SiteFooter/>
- </div>
- );
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/projects/page.tsx b/app/[lng]/engineering/(engineering)/projects/page.tsx
deleted file mode 100644
index 199b175b..00000000
--- a/app/[lng]/engineering/(engineering)/projects/page.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-import * as React from "react"
-import { type SearchParams } from "@/types/table"
-
-import { getValidFilters } from "@/lib/data-table"
-import { Skeleton } from "@/components/ui/skeleton"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { Shell } from "@/components/shell"
-import { ItemsTable } from "@/lib/items/table/items-table"
-import { getProjectLists } from "@/lib/projects/service"
-import { ProjectsTable } from "@/lib/projects/table/projects-table"
-import { searchParamsProjectsCache } from "@/lib/projects/validation"
-
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams
- const search = searchParamsProjectsCache.parse(searchParams)
-
- const validFilters = getValidFilters(search.filters)
-
- const promises = Promise.all([
- getProjectLists({
- ...search,
- filters: validFilters,
- }),
-
- ])
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <h2 className="text-2xl font-bold tracking-tight">
- 프로젝트 리스트 from S-EDP
- </h2>
- {/* <p className="text-muted-foreground">
- S-EDP로부터 수신하는 프로젝트 리스트입니다. 향후 MDG로 전환됩니다.{" "}
- <span className="inline-flex items-center whitespace-nowrap">
- <Ellipsis className="size-3" />
- <span className="ml-1">버튼</span>
- </span>
- 을 통해 담당자 연락처, 입찰 이력, 계약 이력, 패키지 내용 등을 확인 할 수 있습니다.
- </p> */}
- </div>
- </div>
- </div>
-
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- {/* <DateRangePicker
- triggerSize="sm"
- triggerClassName="ml-auto w-56 sm:w-60"
- align="end"
- shallow={false}
- /> */}
- </React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <ProjectsTable promises={promises} />
- </React.Suspense>
- </Shell>
- )
-}
diff --git a/app/[lng]/engineering/(engineering)/report/page.tsx b/app/[lng]/engineering/(engineering)/report/page.tsx
deleted file mode 100644
index 64778ef1..00000000
--- a/app/[lng]/engineering/(engineering)/report/page.tsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import * as React from "react";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Shell } from "@/components/shell";
-import { ErrorBoundary } from "@/components/error-boundary";
-import { getDashboardData } from "@/lib/dashboard/service";
-import { DashboardClient } from "@/lib/dashboard/dashboard-client";
-
-// 데이터 fetch 시 비동기 함수 호출 후 await 하므로 static-pre-render 과정에서 dynamic-server-error 발생.
-// 따라서, dynamic 속성을 force-dynamic 으로 설정하여 동적 렌더링 처리
-// getDashboardData 함수에 대한 Promise를 넘기는 식으로 수정하게 되면 force-dynamic 선언을 제거해도 됨.
-export const dynamic = 'force-dynamic'
-
-export default async function IndexPage() {
- // domain을 명시적으로 전달
- const domain = "engineering";
-
- try {
- // 서버에서 직접 데이터 fetch
- const dashboardData = await getDashboardData(domain);
-
- return (
- <Shell className="gap-2">
- <DashboardClient initialData={dashboardData} />
- </Shell>
- );
- } catch (error) {
- console.error("Dashboard data fetch error:", error);
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-center py-12">
- <div className="text-center space-y-2">
- <p className="text-destructive">데이터를 불러오는데 실패했습니다.</p>
- <p className="text-muted-foreground text-sm">{error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다."}</p>
- </div>
- </div>
- </Shell>
- );
- }
-}
-
-function DashboardSkeleton() {
- return (
- <div className="space-y-6">
- {/* 헤더 스켈레톤 */}
- <div className="flex items-center justify-between">
- <div className="space-y-2">
- <Skeleton className="h-8 w-48" />
- <Skeleton className="h-4 w-72" />
- </div>
- <Skeleton className="h-10 w-24" />
- </div>
-
- {/* 요약 카드 스켈레톤 */}
- <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
- {[...Array(4)].map((_, i) => (
- <div key={i} className="space-y-3 p-6 border rounded-lg">
- <div className="flex items-center justify-between">
- <Skeleton className="h-4 w-16" />
- <Skeleton className="h-4 w-4" />
- </div>
- <Skeleton className="h-8 w-12" />
- <Skeleton className="h-3 w-20" />
- </div>
- ))}
- </div>
-
- {/* 차트 스켈레톤 */}
- <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
- {[...Array(2)].map((_, i) => (
- <div key={i} className="space-y-4 p-6 border rounded-lg">
- <div className="space-y-2">
- <Skeleton className="h-6 w-32" />
- <Skeleton className="h-4 w-48" />
- </div>
- <Skeleton className="h-[300px] w-full" />
- </div>
- ))}
- </div>
-
- {/* 탭 스켈레톤 */}
- <div className="space-y-4">
- <Skeleton className="h-10 w-64" />
- <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
- {[...Array(6)].map((_, i) => (
- <div key={i} className="space-y-4 p-6 border rounded-lg">
- <Skeleton className="h-6 w-32" />
- <div className="space-y-3">
- <div className="flex justify-between">
- <Skeleton className="h-4 w-16" />
- <Skeleton className="h-4 w-12" />
- </div>
- <div className="flex gap-2">
- <Skeleton className="h-6 w-16" />
- <Skeleton className="h-6 w-16" />
- <Skeleton className="h-6 w-16" />
- </div>
- <Skeleton className="h-2 w-full" />
- </div>
- </div>
- ))}
- </div>
- </div>
- </div>
- );
-}
diff --git a/app/[lng]/engineering/(engineering)/tag-numbering/page.tsx b/app/[lng]/engineering/(engineering)/tag-numbering/page.tsx
deleted file mode 100644
index 86ad2ec2..00000000
--- a/app/[lng]/engineering/(engineering)/tag-numbering/page.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import * as React from "react"
-import { type SearchParams } from "@/types/table"
-
-import { getValidFilters } from "@/lib/data-table"
-import { Skeleton } from "@/components/ui/skeleton"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { Shell } from "@/components/shell"
-import { searchParamsCache } from "@/lib/tag-numbering/validation"
-import { getTagNumbering } from "@/lib/tag-numbering/service"
-import { TagNumberingTable } from "@/lib/tag-numbering/table/tagNumbering-table"
-
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams
- const search = searchParamsCache.parse(searchParams)
-
- const validFilters = getValidFilters(search.filters)
-
- const promises = Promise.all([
- getTagNumbering({
- ...search,
- filters: validFilters,
- }),
-
- ])
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <h2 className="text-2xl font-bold tracking-tight">
- 태그 타입 목록 from S-EDP
- </h2>
- {/* <p className="text-muted-foreground">
- 태그 넘버링을 위한 룰셋을 S-EDP로부터 가져오고 확인할 수 있습니다{" "}
- <span className="inline-flex items-center whitespace-nowrap">
- <Ellipsis className="size-3" />
- <span className="ml-1">버튼</span>
- </span>
- 을 통해 담당자 연락처, 입찰 이력, 계약 이력, 패키지 내용 등을 확인 할 수 있습니다.
- </p> */}
- </div>
- </div>
- </div>
-
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- {/* <DateRangePicker
- triggerSize="sm"
- triggerClassName="ml-auto w-56 sm:w-60"
- align="end"
- shallow={false}
- /> */}
- </React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <TagNumberingTable promises={promises} />
- </React.Suspense>
- </Shell>
- )
-}
diff --git a/app/[lng]/engineering/(engineering)/tasks/page.tsx b/app/[lng]/engineering/(engineering)/tasks/page.tsx
deleted file mode 100644
index 91b946fb..00000000
--- a/app/[lng]/engineering/(engineering)/tasks/page.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import * as React from "react"
-import { type SearchParams } from "@/types/table"
-
-import { getValidFilters } from "@/lib/data-table"
-import { Skeleton } from "@/components/ui/skeleton"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { DateRangePicker } from "@/components/date-range-picker"
-import { Shell } from "@/components/shell"
-
-import { FeatureFlagsProvider } from "@/lib/tasks/table/feature-flags-provider"
-import { TasksTable } from "@/lib/tasks/table/tasks-table"
-import {
- getTaskPriorityCounts,
- getTasks,
- getTaskStatusCounts,
-} from "@/lib/tasks/service"
-import { searchParamsCache } from "@/lib/tasks/validations"
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams
- const search = searchParamsCache.parse(searchParams)
-
- const validFilters = getValidFilters(search.filters)
-
- const promises = Promise.all([
- getTasks({
- ...search,
- filters: validFilters,
- }),
- getTaskStatusCounts(),
- getTaskPriorityCounts(),
- ])
-
- return (
- <Shell className="gap-2">
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- <DateRangePicker
- triggerSize="sm"
- triggerClassName="ml-auto w-56 sm:w-60"
- align="end"
- shallow={false}
- />
- </React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <TasksTable promises={promises} />
- </React.Suspense>
- </Shell>
- )
-}
diff --git a/app/[lng]/engineering/(engineering)/tbe/page.tsx b/app/[lng]/engineering/(engineering)/tbe/page.tsx
deleted file mode 100644
index 211cf376..00000000
--- a/app/[lng]/engineering/(engineering)/tbe/page.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import { type SearchParams } from "@/types/table"
-import { getValidFilters } from "@/lib/data-table"
-import { getAllTBE } from "@/lib/rfqs/service"
-import { searchParamsTBECache } from "@/lib/rfqs/validations"
-import { AllTbeTable } from "@/lib/tbe/table/tbe-table"
-import { RfqType } from "@/lib/rfqs/validations"
-import * as React from "react"
-import { Shell } from "@/components/shell"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
-
-interface IndexPageProps {
- params: {
- lng: string
- }
- searchParams: Promise<SearchParams>
-}
-
-// 타입별 페이지 설명 구성 (Budgetary 제외)
-const typeConfig: Record<string, { title: string; description: string; rfqType: RfqType }> = {
- "purchase": {
- title: "Purchase RFQ Technical Bid Evaluation",
- description: "실제 구매 발주 전 가격 요청을 위한 TBE입니다.",
- rfqType: RfqType.PURCHASE
- },
- "purchase-budgetary": {
- title: "Purchase Budgetary RFQ Technical Bid Evaluation",
- description: "프로젝트 수주 후, 공식 입찰 전 예산 책정을 위한 TBE입니다.",
- rfqType: RfqType.PURCHASE_BUDGETARY
- }
-}
-
-export default async function RfqTBEPage(props: IndexPageProps) {
- const resolvedParams = await props.params
- const lng = resolvedParams.lng
-
- // URL 쿼리 파라미터에서 타입 추출
- const searchParams = await props.searchParams
- // 기본값으로 'purchase' 사용
- const typeParam = searchParams?.type as string || 'purchase'
-
- // 유효한 타입인지 확인하고 기본값 설정
- const validType = Object.keys(typeConfig).includes(typeParam) ? typeParam : 'purchase'
- const rfqType = typeConfig[validType].rfqType
-
- // SearchParams 파싱 (Zod)
- const search = searchParamsTBECache.parse(searchParams)
- const validFilters = getValidFilters(search.filters)
-
- // 현재 선택된 타입의 데이터 로드
- const promises = Promise.all([
- getAllTBE({
- ...search,
- filters: validFilters,
- rfqType
- })
- ])
-
- // 페이지 경로 생성 함수 - 단순화
- const getTabUrl = (type: string) => {
- return `/${lng}/evcp/tbe?type=${type}`;
- }
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <h2 className="text-2xl font-bold tracking-tight">
- TBE 관리
- </h2>
- {/* <p className="text-muted-foreground">
- 초대된 협력업체에게 TBE를 보낼 수 있습니다. <br/>
- 체크박스 선택을 하면 초대 버튼이 활성화됩니다. 버튼 클릭 후 첨부파일을 함께 전송하면 TBE 내용이 메일로 전달되고 eVCP에도 협력업체가 입력할 수 있게 자동 생성됩니다.
- </p> */}
- </div>
- </div>
- </div>
-
- {/* 타입 선택 탭 (Budgetary 제외) */}
- <Tabs defaultValue={validType} value={validType} className="w-full">
- <TabsList className="grid grid-cols-2 w-full max-w-md">
- <TabsTrigger value="purchase" asChild>
- <a href={getTabUrl('purchase')}>Purchase</a>
- </TabsTrigger>
- <TabsTrigger value="purchase-budgetary" asChild>
- <a href={getTabUrl('purchase-budgetary')}>Purchase Budgetary</a>
- </TabsTrigger>
- </TabsList>
-
- <div className="mt-2">
- <p className="text-sm text-muted-foreground">
- {typeConfig[validType].description}
- </p>
- </div>
- </Tabs>
-
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <AllTbeTable promises={promises}/>
- </React.Suspense>
- </Shell>
- )
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/vendor-check-list/page.tsx b/app/[lng]/engineering/(engineering)/vendor-check-list/page.tsx
deleted file mode 100644
index e6f9ce82..00000000
--- a/app/[lng]/engineering/(engineering)/vendor-check-list/page.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import * as React from "react"
-import { type SearchParams } from "@/types/table"
-
-import { getValidFilters } from "@/lib/data-table"
-import { Skeleton } from "@/components/ui/skeleton"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { Shell } from "@/components/shell"
-import { getGenralEvaluationsSchema } from "@/lib/general-check-list/validation"
-import { GeneralEvaluationsTable } from "@/lib/general-check-list/table/general-check-list-table"
-import { getGeneralEvaluations } from "@/lib/general-check-list/service"
-
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams
- const search = getGenralEvaluationsSchema.parse(searchParams)
-
- const validFilters = getValidFilters(search.filters)
-
- const promises = Promise.all([
- getGeneralEvaluations({
- ...search,
- filters: validFilters,
- }),
-
- ])
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <h2 className="text-2xl font-bold tracking-tight">
- 협력업체 평가자료 문항 관리
- </h2>
- {/* <p className="text-muted-foreground">
- 협력업체 평가에 사용되는 정기평가 체크리스트를 관리{" "}
- <span className="inline-flex items-center whitespace-nowrap">
- <Ellipsis className="size-3" />
- <span className="ml-1">버튼</span>
- </span>
- 을 통해 담당자 연락처, 입찰 이력, 계약 이력, 패키지 내용 등을 확인 할 수 있습니다.
- </p> */}
- </div>
- </div>
- </div>
-
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- {/* <DateRangePicker
- triggerSize="sm"
- triggerClassName="ml-auto w-56 sm:w-60"
- align="end"
- shallow={false}
- /> */}
- </React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <GeneralEvaluationsTable promises={promises} />
- </React.Suspense>
- </Shell>
- )
-}
diff --git a/app/[lng]/engineering/(engineering)/vendor-data/form/[packageId]/[formId]/[projectId]/[contractId]/page.tsx b/app/[lng]/engineering/(engineering)/vendor-data/form/[packageId]/[formId]/[projectId]/[contractId]/page.tsx
deleted file mode 100644
index f69aa525..00000000
--- a/app/[lng]/engineering/(engineering)/vendor-data/form/[packageId]/[formId]/[projectId]/[contractId]/page.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import DynamicTable from "@/components/form-data/form-data-table";
-import { findContractItemId, getFormData, getFormId } from "@/lib/forms/services";
-
-interface IndexPageProps {
- params: {
- lng: string;
- packageId: string;
- formId: string;
- projectId: string;
- contractId: string;
-
-
- };
- searchParams?: {
- mode?: string;
- };
-}
-
-export default async function FormPage({ params, searchParams }: IndexPageProps) {
- // 1) 구조 분해 할당
- const resolvedParams = await params;
-
- // 2) searchParams도 await 필요
- const resolvedSearchParams = await searchParams;
-
- // 3) 구조 분해 할당
- const { lng, packageId, formId: formCode, projectId,contractId } = resolvedParams;
-
- // URL 쿼리 파라미터에서 mode 가져오기 (await 해서 사용)
- const mode = resolvedSearchParams?.mode === "ENG" ? "ENG" : "IM"; // 기본값은 IM
-
- // 4) 변환
- let packageIdAsNumber = Number(packageId);
- const contractIdAsNumber = Number(contractId);
-
- // packageId가 0이면 contractId와 formCode로 실제 contractItemId 찾기
- if (packageIdAsNumber === 0 && contractIdAsNumber > 0) {
- console.log(`packageId가 0이므로 contractId ${contractIdAsNumber}와 formCode ${formCode}로 contractItemId 조회`);
-
- const foundContractItemId = await findContractItemId(contractIdAsNumber, formCode);
-
- if (foundContractItemId) {
- console.log(`contractItemId ${foundContractItemId}를 찾았습니다. 이 값을 사용합니다.`);
- packageIdAsNumber = foundContractItemId;
- } else {
- console.warn(`contractItemId를 찾을 수 없습니다. packageId는 계속 0으로 유지됩니다.`);
- }
- }
-
- // 5) DB 조회
- const { columns, data, editableFieldsMap } = await getFormData(formCode, packageIdAsNumber);
-
-
- // 6) formId 및 report temp file 조회
- const { formId } = await getFormId(String(packageIdAsNumber), formCode);
-
- // 7) 예외 처리
- if (!columns) {
- return (
- <p className="text-red-500">해당 폼의 메타 정보를 불러올 수 없습니다. ENG 모드의 경우에는 SHI 관리자에게 폼 생성 요청을 하시기 바랍니다.</p>
- );
- }
-
- // 8) 렌더링
- return (
- <div className="space-y-6">
- <DynamicTable
- contractItemId={packageIdAsNumber}
- formCode={formCode}
- formId={formId}
- columnsJSON={columns}
- dataJSON={data}
- projectId={Number(projectId)}
- editableFieldsMap={editableFieldsMap} // 새로 추가
- mode={mode} // 모드 전달
- />
- </div>
- );
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/vendor-data/layout.tsx b/app/[lng]/engineering/(engineering)/vendor-data/layout.tsx
deleted file mode 100644
index 7d00359c..00000000
--- a/app/[lng]/engineering/(engineering)/vendor-data/layout.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-// app/vendor-data/layout.tsx
-import * as React from "react"
-import { cookies } from "next/headers"
-import { Shell } from "@/components/shell"
-import { getVendorProjectsAndContracts } from "@/lib/vendor-data/services"
-import { VendorDataContainer } from "@/components/vendor-data/vendor-data-container"
-import { InformationButton } from "@/components/information/information-button"
-// Layout 컴포넌트는 서버 컴포넌트입니다
-export default async function VendorDataLayout({
- children,
-}: {
- children: React.ReactNode
-}) {
- // evcp: 전체 계약 대상으로 프로젝트 데이터 가져오기
- const projects = await getVendorProjectsAndContracts()
-
- // 레이아웃 설정 쿠키 가져오기
- // Next.js 15에서는 cookies()가 Promise를 반환하므로 await 사용
- const cookieStore = await cookies()
-
- // 이제 cookieStore.get() 메서드 사용 가능
- const layout = cookieStore.get("react-resizable-panels:layout:mail")
- const collapsed = cookieStore.get("react-resizable-panels:collapsed")
-
- const defaultLayout = layout ? JSON.parse(layout.value) : undefined
- const defaultCollapsed = collapsed ? JSON.parse(collapsed.value) : undefined
-
- return (
- <Shell className="gap-2">
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <div className="flex items-center gap-2">
- <h2 className="text-2xl font-bold tracking-tight">
- 협력업체 데이터 입력
- </h2>
- <InformationButton pagePath="partners/vendor-data" />
- </div>
- {/* <p className="text-muted-foreground">
- 각종 Data 입력할 수 있습니다
- </p> */}
- </div>
- </div>
- </div>
-
- <section className="overflow-hidden rounded-[0.5rem] border bg-background shadow">
- <div className="hidden flex-col md:flex">
- {projects.length === 0 ? (
- <div className="p-4 text-center text-sm text-muted-foreground">
- No projects found for this vendor.
- </div>
- ) : (
- <VendorDataContainer
- projects={projects}
- defaultLayout={defaultLayout}
- defaultCollapsed={defaultCollapsed}
- navCollapsedSize={4}
- >
- {/* 페이지별 콘텐츠가 여기에 들어갑니다 */}
- {children}
- </VendorDataContainer>
- )}
- </div>
- </section>
- </Shell>
- )
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/vendor-data/page.tsx b/app/[lng]/engineering/(engineering)/vendor-data/page.tsx
deleted file mode 100644
index ddc21a2b..00000000
--- a/app/[lng]/engineering/(engineering)/vendor-data/page.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-// evcp/vendor-data/page.tsx - 전체 계약 대상 협력업체 데이터
-import * as React from "react"
-import { Separator } from "@/components/ui/separator"
-
-export default async function IndexPage() {
- return (
- <div className="space-y-6">
- <div>
- <h3 className="text-lg font-medium">전체 계약 협력업체 데이터 대시보드</h3>
- <p className="text-sm text-muted-foreground">
- 모든 계약의 협력업체 데이터를 확인하고 관리할 수 있습니다.
- </p>
- </div>
- <Separator />
- <div className="grid gap-4">
- <div className="rounded-lg border p-4">
- <h4 className="text-sm font-medium">사용 방법</h4>
- <p className="text-sm text-muted-foreground mt-1">
- 1. 왼쪽 사이드바에서 계약을 선택하세요.<br />
- 2. 선택한 계약의 패키지 항목을 클릭하세요.<br />
- 3. 패키지의 태그 정보를 확인하고 관리할 수 있습니다.<br />
- 4. 폼 항목을 클릭하여 칼럼 정보를 확인하고 관리할 수 있습니다.
- </p>
- </div>
- </div>
- </div>
- )
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/vendor-data/tag/[id]/page.tsx b/app/[lng]/engineering/(engineering)/vendor-data/tag/[id]/page.tsx
deleted file mode 100644
index 7250732f..00000000
--- a/app/[lng]/engineering/(engineering)/vendor-data/tag/[id]/page.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import { Separator } from "@/components/ui/separator"
-import { type SearchParams } from "@/types/table"
-import { getValidFilters } from "@/lib/data-table"
-import { TagsTable } from "@/lib/tags/table/tag-table"
-import { searchParamsCache } from "@/lib/tags/validations"
-import { getTags } from "@/lib/tags/service"
-
-interface IndexPageProps {
- params: {
- id: string
- }
- searchParams: Promise<SearchParams>
-}
-
-export default async function TagPage(props: IndexPageProps) {
- const resolvedParams = await props.params
- const id = resolvedParams.id
-
- const idAsNumber = Number(id)
-
- // 2) SearchParams 파싱 (Zod)
- // - "filters", "page", "perPage", "sort" 등 contact 전용 컬럼
- const searchParams = await props.searchParams
- const search = searchParamsCache.parse(searchParams)
- const validFilters = getValidFilters(search.filters)
-
- const promises = Promise.all([
- getTags({
- ...search,
- filters: validFilters,
- },
- idAsNumber)
- ])
-
- // 4) 렌더링
- return (
- <div className="space-y-6">
- <div>
- <TagsTable promises={promises} selectedPackageId={idAsNumber}/>
- </div>
- </div>
- )
-} \ No newline at end of file
diff --git a/app/[lng]/engineering/(engineering)/vendor-investigation/page.tsx b/app/[lng]/engineering/(engineering)/vendor-investigation/page.tsx
deleted file mode 100644
index af9f3e11..00000000
--- a/app/[lng]/engineering/(engineering)/vendor-investigation/page.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import * as React from "react"
-import { type SearchParams } from "@/types/table"
-
-import { getValidFilters } from "@/lib/data-table"
-import { Skeleton } from "@/components/ui/skeleton"
-import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
-import { Shell } from "@/components/shell"
-
-import { VendorsInvestigationTable } from "@/lib/vendor-investigation/table/investigation-table"
-import { getVendorsInvestigation } from "@/lib/vendor-investigation/service"
-import { searchParamsInvestigationCache } from "@/lib/vendor-investigation/validations"
-
-interface IndexPageProps {
- searchParams: Promise<SearchParams>
-}
-
-export default async function IndexPage(props: IndexPageProps) {
- const searchParams = await props.searchParams
- const search = searchParamsInvestigationCache.parse(searchParams)
-
- const validFilters = getValidFilters(search.filters)
-
- const promises = Promise.all([
- getVendorsInvestigation({
- ...search,
- filters: validFilters,
- }),
- ])
-
- return (
- <Shell className="gap-2">
-
- <div className="flex items-center justify-between space-y-2">
- <div className="flex items-center justify-between space-y-2">
- <div>
- <h2 className="text-2xl font-bold tracking-tight">
- 협력업체 실사 관리
- </h2>
- {/* <p className="text-muted-foreground">
- 요청된 Vendor 실사에 대한 스케줄 정보를 관리하고 결과를 입력할 수 있습니다.
-
- </p> */}
- </div>
- </div>
- </div>
-
-
- <React.Suspense fallback={<Skeleton className="h-7 w-52" />}>
- </React.Suspense>
- <React.Suspense
- fallback={
- <DataTableSkeleton
- columnCount={6}
- searchableColumnCount={1}
- filterableColumnCount={2}
- cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]}
- shrinkZero
- />
- }
- >
- <VendorsInvestigationTable promises={promises}/>
- </React.Suspense>
- </Shell>
- )
-}